local SkillExcel	= require("excel.Skill").Skill
local UtilityExcel	= require("excel.Skill").Utility
local ActionType	= require("excel.Skill").ActionType
local Obj 			= require("core.Obj")
local Msg 			= require("core.Msg")
local Timer			= require("core.Timer")
local Util			= require("common.Util")
local SkillDefine	= require("skill.Define")
local EffectLogic	= require("scene.EffectLogic")
local Skill			= require("skill.Skill")
local CoolDown		= require("skill.CoolDown")
local Conditions	= require("skill.Conditions")	-- 条件
local BufferCmds  = require("buffer.Cmds")
local ObjHuman = require("core.ObjHuman")
local ShenbingExcel = require("excel.Shenbing").shenbing
local BufferExcel = require("excel.Buffer").Buff
local HorseLogic = require("horse.HorseLogic")
local ItemDefine = require("bag.ItemDefine")
local ObjMonster = require("core.ObjMonster")
local BaowuLogic = require("baowu.BaowuLogic")
local QiliaoLogic = require("qiliao.QiliaoLogic")

HIDE_NO_SEND_MAP = {[3006] = 1}
local SkillGroup = nil
local function init_group()
    SkillGroup = {}
    for id, skill in pairs(SkillExcel) do
        if skill.group ~= 0 and skill.isSkillCall  == 0 and skill.isJuexing == 0 then
            SkillGroup[skill.group] = SkillGroup[skill.group] or {}
            SkillGroup[skill.group][#SkillGroup[skill.group]+1] = id
        end
        if #skill.link >0 then
            SkillExcel[skill.link[1][1]].linkparent = id
        end
    end
    
    for k,v in pairs(SkillGroup) do
        table.sort(v)
    end
end
init_group()

local function setSkillGroup(human, skillId, skillLv, mm, len)
    local skill = SkillExcel[skillId]
    local groups = SkillGroup[skill.group]
    if groups == nil then
         groups = {skillId}
    end
    for j = 1, #groups do
        len = len + 1
        setSkillData(human,groups[j],mm.list[len], skillLv)
    end
    return len
end
-- 下发角色技能列表
function GC_SKILL_LIST(human)
	local mm = Msg.gc.GC_SKILL_LIST
	local len = 0
	mm.list[0] = len   
 
  if human.db.putonShenbing == 0 then
       Msg.send(mm,human.fd)
       return
  end
  local data = ObjHuman.getShenbing(human, human.db.putonShenbing)
  if data == nil then
        Msg.send(mm,human.fd)
        return
  end
  local config = ShenbingExcel[human.db.putonShenbing]
  if not config then
        Msg.send(mm,human.fd)
        return
  end
	for i = 1,#config.haveSkill do	   
	    local id = config.haveSkill[i]
	    local skill = SkillExcel[id]
	    if skill.group~= 0 and id ~= skill.group then
	       assert()
	    end
	    local groups = SkillGroup[skill.group]
	    if groups == nil then
	       groups = {id}
	    end
	    local skillLv = data.skillLv[i-1] 
	    
	    for j = 1, #groups do
	       id = groups[j]
	       skill = SkillExcel[id]
			   local mainUtility = skill.mainUtility	
			   local mainUtilityConfig = UtilityExcel[mainUtility]
			   if mainUtilityConfig then
				    len = len+1
				    setSkillData(human,id,mm.list[len], skillLv, ObjHuman.getSkillLevelUp(human,skill.group))						 
				 end
			end
	end	
	local skillId, skillLv = HorseLogic.getHorseSkill(human)
	if skillId then
	   len = setSkillGroup(human,skillId, skillLv,mm, len)
	end
	skillId, skillLv = BaowuLogic.getBaowuSkill(human)
	if skillId then
	   len = setSkillGroup(human,skillId, skillLv, mm, len)
	end
	skillId, skillLv = QiliaoLogic.getQiliaoSkill(human)
	if skillId then
	   len = setSkillGroup(human,skillId, skillLv, mm, len)
  end	
	mm.list[0] = len		
	Msg.send(mm,human.fd)
end


function GC_SKILL_LIST_CHANGE(human, no_always_send)
	assert(human.obj_type == Obj.TYPE_HUMAN)
	local mm = Msg.gc.GC_SKILL_LIST_CHANGE
	local len = 0	
	if human.bufAttr.awake or human.bufAttr.skillChange then 
		local config 
		if human.bufAttr.awake then
      config = BufferExcel[human.bufAttr.awake]
    else
		  config = BufferExcel[human.bufAttr.skillChange]
		end
		local skill
		for _,id in ipairs(config.arg) do
		  skill = SkillExcel[id]			
			while skill do
				local mainUtility = skill.mainUtility	
				local mainUtilityConfig = UtilityExcel[mainUtility]
				if mainUtilityConfig then
					len = len+1
					setSkillData(human,id,mm.list[len],1)
				end
				
				if skill.link[1] then
				    id = skill.link[1][1]
				    skill = SkillExcel[id]				    
				else
				    skill = nil
				end
			end
		end	
	end

	mm.list[0] = len
	if not no_always_send or 0 < len then	
		Msg.send(mm,human.fd)
	end
end

local FRIENDFOE_TYPE_TEAM		= 5
local FRIENDFOE_TYPE_TEAM_HUMAN = 6
local FRIENDFOE_TYPE_NOT_ENEMY	= 9
local FRIENDFOE_TYPE_FRIEND		= 10

function setSkillData(human,id,SkillData, skillLv, skillLvUp, isOther)	
	local skill = SkillExcel[id]
	local mainUtility = skill.mainUtility	
	local mainUtilityConfig = UtilityExcel[mainUtility]
	local groupSkill = SkillExcel[skill.group]
	SkillData.id = id
	SkillData.name = skill.name
	SkillData.icon = skill.icon
	SkillData.level = skillLv > 0 and skillLv or 1
	SkillData.levelUp = skillLvUp or 0
	SkillData.cooldown = skill.coolDown
	SkillData.group = skill.group
	SkillData.element = 0
	SkillData.isNormal = skill.isNormal
	SkillData.isJuexing = skill.isJuexing
	SkillData.skillType = skill.skillType
	SkillData.actionType = mainUtilityConfig.actionType
	SkillData.mp = 0
	local conditions = mainUtilityConfig.friendAndFoeConditions
	SkillData.isGood = (conditions == FRIENDFOE_TYPE_TEAM or conditions == FRIENDFOE_TYPE_TEAM_HUMAN or 
						conditions == FRIENDFOE_TYPE_NOT_ENEMY or conditions == FRIENDFOE_TYPE_FRIEND) and 1 or 0
						
	SkillData.giddyCanSkill = skill.giddyCanSkill
	SkillData.canSkill = skill.canSkill
	
	for _,v in ipairs(skill.loss) do
		if v[1]=="mp" then
			SkillData.mp =  v[2]
			break
		end		
	end
	
	SkillData.isLoop = skill.isLoop
	SkillData.hang = skill.hang			
	
	SkillData.isActivation = skillLv>0 and 1 or 0
	
	local sbName = ""
	local sbLv = 0
	local money = 0
	local itemID = 0
	local itemCnt = 0
	local conditionList
	local petStageLv = 0
	local zhangong = 0
	local horseLv = 0
	local baowuLv = 0
	if groupSkill then
		if SkillData.isActivation ==1 then
			conditionList = groupSkill.upgradeCondition[SkillData.level]
		else
			conditionList = skill.activationCondition
		end
		
	  if skill.sb and ShenbingExcel[skill.sb] then  --神兵
      sbName = ShenbingExcel[skill.sb].sbMingzi
    end
	end
	if conditionList then
		for _,v in ipairs(conditionList) do
			if v[1]=="money" then
				money = v[2]
			elseif v[1] == "sblevel" or v[1] == "petlevel" then
			  sbLv = v[2]
			elseif v[1] == "item" then
			  itemID = v[2]
			  itemCnt = v[3]
			elseif v[1] == "lv" then
        sbLv = v[2]
      elseif v[1] == "petStageLv" then
        petStageLv = v[2]
      elseif v[1] == "zhangong" then
        zhangong = v[2]
      elseif v[1] == "horseLv" then
        horseLv = v[2]
      elseif v[1] == "baowuLv" then
        baowuLv = v[2]    
		  end
		end
	end
	
	SkillData.upMoney = money
	SkillData.sbName =  sbName
	SkillData.sbLv   =  sbLv
	SkillData.itemID = itemID
	SkillData.itemCnt = itemCnt
	SkillData.itemName = ItemDefine.getValue(itemID, "name") or ""
	SkillData.petStageLv = petStageLv
	SkillData.zhangong = zhangong
	SkillData.horseLv = horseLv
	SkillData.baowuLv = baowuLv

	if not isOther then
  	local info = CoolDown.getCoolDown(human, id)
  	if SkillData.isActivation == 1 then
  	   CoolDown.calcCoolDown(human, id)	--重新计算冷却豆子
  		if skill.coolDownCount >1 then	--冷却豆子处理		   
  		   SkillData.count = info and info.count or 0
  	  else
  		    SkillData.count = 0
  	  end
  	else
  	  SkillData.count = 0
  	end
  	 
    local now    = Timer.now
    if not info or now - info.time > skill.coolDown or (SkillData.count>1 and SkillData.count>=skill.coolDownCount) then
      SkillData.time = 0
    else
      SkillData.time = skill.coolDown - (now - info.time)
    end 
  else
    SkillData.count = 0
    SkillData.time = 0
  end
	

	
	SkillData.qianyao  = skill.qianyao_sec*1000
	SkillData.maxCount = skill.coolDownCount	
	SkillData.acttackType = mainUtilityConfig.acttackType
	SkillData.attackLen = Skill.getAttackLen(id)
end

gridsCache = gridsCache or {}
-- 主菜单技能快捷栏
function GC_SKILL_MAIN_MENU(human)
	local mm = Msg.gc.GC_SKILL_MAIN_MENU

	mm.itemDatas[0] = 0
	mm.id[0] = 0	
	local config = ShenbingExcel[human.db.putonShenbing]
	mm.weapon = config and config.icon[1] or 0
	if not BufferCmds.other.awake(human, mm) then
	 if not BufferCmds.other.skillChange(human,mm) then	--如果没有技能栏切换 那么使用默认
	   local data = ObjHuman.getShenbing(human, human.db.putonShenbing)
     if data and config then
         local len = #config.haveSkill
         if len > 4 then
            len= 4
         end
		     for i = 1,len do
			     mm.id[0] = mm.id[0] + 1
			     mm.id[mm.id[0]] = config.haveSkill[i]
		     end
		     mm.weapon = data.jinhua == 1 and config.icon[2] or config.icon[1]
		 end  
		 
		 local skillid = HorseLogic.getHorseSkill(human)
     mm.horseSkill = skillid or 0
     skillid = BaowuLogic.getBaowuSkill(human)
     mm.bowSkill = skillid or 0
     skillid = QiliaoLogic.getQiliaoSkill(human)
     mm.qiliaoSkill = skillid or 0     
     BufferCmds.other.oneSkillChange(human, mm)   
	 end  
	end	


	Msg.send(mm,human.fd)
end

function GC_SKILL_CHANGE_ONE(human, pos, skillID)
  local msg = Msg.gc.GC_SKILL_CHANGE_ONE
  msg.pos = pos
  msg.skillID = skillID
  Msg.send(msg, human.fd)
end

local unit			= {}
function GC_SKILL_FIRE(obj, oldSkillID, skillID, tx, ty, x, y, target)

	local skillConfig		= SkillExcel[skillID]
	local skillConfigOld 	= SkillExcel[oldSkillID]
	local mm				= Msg.gc.GC_SKILL_FIRE
	local mainUtilityConfig = UtilityExcel[skillConfig.mainUtility]
	local mustUtilityConfig = UtilityExcel[skillConfig.mustUtility]
	local utilityConfig
	
	if not mainUtilityConfig then return end
	
	if obj.obj_type == Obj.TYPE_HUMAN then
		if Conditions.prerequisites(obj, target, nil, mainUtilityConfig) then
			utilityConfig = mainUtilityConfig
		elseif Conditions.prerequisites(obj, target, nil, mustUtilityConfig) then
			utilityConfig = mustUtilityConfig
		else
			return
		end
		
		local now			  = Timer.now 
		local info		  = CoolDown.getCoolDown(obj, oldSkillID)
				
		if not info or now - info.time > skillConfigOld.coolDown then
			mm.time = 0
		else
			mm.time = skillConfigOld.coolDown - (now - info.time)
		end	
		
		if skillConfigOld.coolDownCount >1 then	--冷却豆子处理
		  
			mm.count = info and info.count or 0
		else
			mm.count = 0
		end
	else
		utilityConfig = mainUtilityConfig
		mm.time		  = 0
		mm.count	  = 0
	end
	
	if utilityConfig.actionType==0 then return end
	
	mm.send_id				= obj.id
	mm.skill_id				= oldSkillID
	mm.recv_id				= target and target.id or 0
	mm.x, mm.y, mm.tx,mm.ty = x, y, tx, ty
	
	local action_id, actionIndex = Skill.getAction(obj, skillID, skillConfig)
	mm.horse_action = skillConfig.horseActionID
	mm.enableID 	= utilityConfig.enableID[actionIndex] or 0
	mm.attackID 	= utilityConfig.attackID
	mm.enableConfig = EffectLogic.getConfig(mm.enableID)
	mm.effectConfig = EffectLogic.getConfig(mm.attackID)
	mm.action_id	= action_id	--获取不同的播放动作
	mm.quake		= getQuake(obj, skillConfig.actionQuake)
	mm.fireSound = skillConfig.fireSound
	
	if mainUtilityConfig.utility == "rush" or mainUtilityConfig.utility == "jumpTo"  then
	   mm.qianyao = 0
	else
	   mm.qianyao = skillConfig.qianyao_sec*1000
     if mm.qianyao>0 and mm.qianyao < 200 then
      mm.qianyao = 200
     end
  end
	mm.show_icon = skillConfig.skill_use_icon
	mm.move_cancel = utilityConfig.move_canel
	mm.timescale = skillConfig.timescale
	local sceneID = obj.scene_id
  if obj.obj_type == Obj.TYPE_HUMAN and HIDE_NO_SEND_MAP[obj.db.map_id] then
        local list = Msg.list
        Obj.getAreaHumans(list, sceneID, obj.x, obj.y)
        for k = 1, list[0] do
            local tempObj = list[k]
            if tempObj.db.hide == 0 or tempObj==obj then
                Msg.send(mm, tempObj.fd)
            end
        end
  else
	      Obj.sendArea(mm, sceneID, obj.x, obj.y)
	end
	if ActionType[utilityConfig.actionType].specialFire == 1 then
		GC_SKILL_ACTION(obj, sceneID, skillID, skillConfig, utilityConfig, tx, ty, x, y, target)
	end
end


function GC_SKILL_MAGIC_FLY(obj, sceneID, skillID, skillConfig, utilityConfig, tx, ty, x, y, target)

	local actionTypeConfig = ActionType[utilityConfig.actionType]	
	if not actionTypeConfig then return end
	
	if utilityConfig.actionType == SkillDefine.ACTION_TYPE_BESSEL_REVERSE and utilityConfig.hitID~=0 then	-- 反向贝塞尔曲线特殊处理
		local mm			= Msg.gc.GC_SKILL_BOMB		
		local acttackCenter = utilityConfig.acttackCenter
		if acttackCenter == ACTTACK_TYPE_SELF then
			mm.tx = x
			mm.ty =	y
		elseif target and acttackCenter == ACTTACK_TYPE_LOCK_TARGET then
			mm.tx = target.x
			mm.ty =	target.y
		else
			mm.tx = tx
			mm.ty =	ty
		end
	
		local hitID		= utilityConfig.hitID
		mm.bomb_id		= hitID
		mm.effectConfig = EffectLogic.getConfig( hitID )
		mm.bombSound	= utilityConfig.hitSound
		
		Obj.sendArea(mm, sceneID, mm.tx, mm.ty)
	end

	if actionTypeConfig.specialFly== 1 then
		GC_SKILL_ACTION(obj, sceneID, skillID, skillConfig, utilityConfig, tx, ty, x, y, target)
	end
	
	if actionTypeConfig.normalFly ~= 1 or utilityConfig.flyID==0 then
		return
	end
	
	local mm = Msg.gc.GC_SKILL_MAGIC_FLY
--	if unit.targetFly or utilityConfig.multiTarget>0 then
  if unit.targetFly then
		mm.send_id = 0
	else
		mm.send_id = obj.id
	end

	mm.recv_id = target and target.id or 0
	mm.tx = tx
	mm.ty = ty
	mm.x  = x
	mm.y  = y
	
	local gravity = utilityConfig.actionArg[3]
	mm.gravity = gravity and gravity*100 or 0.3*100
	
	--assert(utilityConfig.flySpeed~=0," flySpeed==0 utilityID:"..skillID)
	
	local flyID			= utilityConfig.flyID
	local tailID		= utilityConfig.tailID
	
	mm.actionType		= utilityConfig.actionType
	mm.flySpeed			= utilityConfig.flySpeed
	mm.flyID			= flyID
	mm.flyEffectConfig	= EffectLogic.getConfig(flyID)
	mm.tailID			= tailID
	mm.tailEffectConfig	= EffectLogic.getConfig(tailID)
	if obj.obj_type == Obj.TYPE_HUMAN and HIDE_NO_SEND_MAP[obj.db.map_id] then
	      local list = Msg.list
        Obj.getAreaHumans(list, sceneID, obj.x, obj.y)
        for k = 1, list[0] do
            local tempObj = list[k]
            if tempObj.db.hide == 0 or tempObj==obj then
                Msg.send(mm, tempObj.fd)
            end
        end
  else
	     Obj.sendArea(mm, sceneID, x, y)
	end
end

local getTargetPoint = Util.getTargetPoint
local resKey = {"actionID","flySpeed","enableID","attackID","effectConfig","flyID","flyEffectConfig","tailID","tailEffectConfig","hitID","bombID","hitSound","bombSound","radius", "bombEffectConfig"}
function GC_SKILL_ACTION(obj, sceneID, skillID, skillConfig, utilityConfig, tx, ty, x, y, target)

	local targetID  = target and target.id or 0
	local mm = Msg.gc.GC_SKILL_ACTION
	mm.send_id		= obj.id
	mm.skill_id 	= skillID
	mm.recv_id		= targetID
	mm.actionType	= utilityConfig.actionType
	
	local otherArgsLen = 0
	if utilityConfig.actionType == SkillDefine.ACTION_TYPE_LINE_COMBO  then	--线性特效组合
		local width = utilityConfig.aoeArgs[1]
		mm.tx,mm.ty = getTargetPoint(tx, ty, x, y, width)
		local hasDist
		if #utilityConfig.specialConditions >0 then
			for _,value in ipairs(utilityConfig.specialConditions) do
				if value[1]=="dist" then
					mm.tx,mm.ty = getTargetPoint(tx, ty, x, y, value[3])
					mm.x, mm.y  = getTargetPoint(mm.tx, mm.ty, x, y, value[2])
					hasDist = true
					break
				end
			end
		end
		if #utilityConfig.specialConditions == 0 or not hasDist then
			mm.x, mm.y = getTargetPoint(tx, ty, x, y, 10)
		end
		
	elseif utilityConfig.actionType == SkillDefine.ACTION_TYPE_FAN_COMBO  then	--扇形特效组合
		local radius = utilityConfig.actionArg[3]
		mm.tx,mm.ty  = getTargetPoint(tx, ty, x, y, radius)				
		mm.x,mm.y	 = getTargetPoint(tx, ty, x, y, 10)
		
	elseif utilityConfig.actionType == SkillDefine.ACTION_TYPE_FAN_SPREAD_COMBO  then	--扇形扩散特效组合
		mm.x, mm.y	 = x,  y
		mm.tx,mm.ty  = tx, ty
	else

		if utilityConfig.actionType == SkillDefine.ACTION_TYPE_PULL then
			mm.recv_id = targetID
			mm.tx,mm.ty = tx, ty
	  elseif utilityConfig.actionType == SkillDefine.ACTION_TYPE_JUMPTO then
	    mm.recv_id = targetID
	    mm.tx,mm.ty = tx, ty
	  elseif utilityConfig.actionType == SkillDefine.ACTION_TYPE_JUMP then
	    mm.recv_id = targetID
	    mm.tx, mm.ty = tx, ty
		elseif utilityConfig.actionType == SkillDefine.ACTION_TYPE_RUSH then
			mm.recv_id = targetID
			mm.tx,mm.ty = tx,ty
			
			local userData = Skill.getUserData(obj)
			if userData[4] then
				otherArgsLen = 3
				mm.otherArgs[1] = userData[1]
				mm.otherArgs[2] = userData[2]
				mm.otherArgs[3] = userData[3] and 1 or 0
			end		
		else
			if utilityConfig.acttackCenter == SkillDefine.ACTTACK_TYPE_SELF then
				mm.tx = x
				mm.ty = y
			elseif utilityConfig.acttackCenter == SkillDefine.ACTTACK_TYPE_MOUSE_POINT then
				mm.tx = tx
				mm.ty = ty
			else
				if target then
					mm.tx = target.x
					mm.ty = target.y
				else
					mm.tx = tx
					mm.ty = ty
				end
				
				mm.recv_id = targetID
			end
		
		end
		
		mm.x = x
		mm.y = y		
	end
	
	mm.otherArgs[0] = otherArgsLen
	
	local actionArg = utilityConfig.actionArg
	
	--参数
	local actionArgs = mm.actionArgs
	local besselStyle = obj.besselStyle or 1
	if utilityConfig.actionType == SkillDefine.ACTION_TYPE_BESSEL_ONE  then
		besselStyle = besselStyle==1 and -1 or 1
		obj.besselStyle = besselStyle
		actionArgs[1] = besselStyle
		actionArgs[0] = 1
	else
		for i,arg in ipairs(actionArg) do
			actionArgs[i] = arg
		end
		actionArgs[0] = #actionArg
	end
	
	--资源	
	local action_id,actionIndex = Skill.getAction(obj, skillID, skillConfig)
	
	local resLen = 0
	local resList = mm.resList
	for i,key in ipairs(resKey) do
		local value 
		if key=="effectConfig" then
			local attackID = utilityConfig.attackID
			value = attackID and EffectLogic.getConfig(attackID) or nil
		elseif key=="flyEffectConfig" then
			local flyID = utilityConfig.flyID
			value = flyID and EffectLogic.getConfig(flyID) or nil
		elseif key=="tailEffectConfig" then
			local tailID = utilityConfig.tailID
			value = tailID and EffectLogic.getConfig(tailID) or nil
		elseif key=="enableID" then
			local v = utilityConfig.enableID[actionIndex]
			if v~=0 then value = v end
		elseif key=="actionID" then
			if action_id~=-1 then
				value = action_id	--获取不同的播放动作
			end
		elseif key=="radius" then
			value = utilityConfig.aoeArgs[1]
	  elseif key=="bombEffectConfig" then
	    local bombID = utilityConfig.bombID
	    value = bombID and  EffectLogic.getConfig(bombID) or nil
		else
			local v = utilityConfig[key]
			if v~=0 then
				value = v
			end
		end		
		if value then
			resLen = resLen+1
			resList[resLen].key = i
			resList[resLen].value = value
		end 
	end
	
	mm.multiTarget = utilityConfig.multiTarget>0 and 1 or 0
	resList[0] = resLen
	--Obj.sendAreaRadius(mm, unit.sceneID, unit.x, unit.y,2000)
	
	if obj.obj_type == Obj.TYPE_HUMAN and HIDE_NO_SEND_MAP[obj.db.map_id] then
        local list = Msg.list
        Obj.getAreaHumans(list, sceneID, obj.x, obj.y)
        for k = 1, list[0] do
            local tempObj = list[k]
            if tempObj.db.hide == 0 or tempObj==obj then
                Msg.send(mm, tempObj.fd)
            end
        end
  else
	      Obj.sendArea(mm, sceneID, x, y)
	end
end

function GC_SKILL_BOMB(obj, sceneID, skillID, skillConfig, utilityConfig, tx, ty, x, y, target)

	local actionTypeConfig = ActionType[utilityConfig.actionType]
	if not actionTypeConfig then return end
		
	if actionTypeConfig.specialBomb == 1 then
		GC_SKILL_ACTION(obj, sceneID, skillID, skillConfig, utilityConfig, tx, ty, x, y, target)
	end
	
	local bombID = utilityConfig.bombID
	if utilityConfig.actionType == SkillDefine.ACTION_TYPE_BESSEL_REVERSE and bombID~=0 then
		local mm = Msg.gc.GC_SKILL_HIT2
		mm.recv_id			= obj.id
		mm.hit_id			= bombID
		mm.hit_height = utilityConfig.hitHeight
		mm.hitEffectConfig  = EffectLogic.getConfig(bombID)
		Obj.sendArea(mm, sceneID, x, y)
		return
	end
	
	if actionTypeConfig.normalBomb ~= 1 or bombID == 0 then
		return
	end
	
	local mm			= Msg.gc.GC_SKILL_BOMB		
	local acttackCenter = utilityConfig.acttackCenter
	if acttackCenter == SkillDefine.ACTTACK_TYPE_SELF then
		mm.tx = x
		mm.ty =	y
	elseif target and acttackCenter == SkillDefine.ACTTACK_TYPE_LOCK_TARGET then
		mm.tx = target.x
		mm.ty =	target.y
	else
		mm.tx = tx
		mm.ty =	ty
	end
	
	mm.bomb_id		= bombID
	mm.effectConfig = EffectLogic.getConfig(bombID)
	mm.bombSound	= utilityConfig.bombSound

	Obj.sendArea(mm, sceneID, mm.tx, mm.ty)
end

function GC_SKILL_HIT(obj, senderID, hurtHp, heavyHit, utilityConfig)
	local mm		= Msg.gc.GC_SKILL_HIT	
	mm.hurt_hp  	= hurtHp
	mm.recv_id  	= obj.id
	mm.send_id  	= senderID
	mm.obj_hp   	= Obj.getHp(obj)
	mm.obj_max_hp   = Obj.getHpMax(obj)

	local hitID
	local hitHeight
	local hitEffectConfig
	local isStiff
	if utilityConfig and utilityConfig.actionType ~= SkillDefine.ACTION_TYPE_BESSEL_REVERSE then
		hitID			= utilityConfig.hitID
		hitHeight = utilityConfig.hitHeight
		hitEffectConfig = EffectLogic.getConfig(hitID)
		local hitCount	= utilityConfig.hitCount
		mm.hitCount 	= hitCount>1 and hitCount or 1
	else
		hitID			= 0
		hitHeight = 0
		mm.hitCount 	= 1
	end
	
	if hurtHp>0 and obj.obj_type == Obj.TYPE_MONSTER then
		if obj.stiff_time and Timer.now < obj.stiff_time then
			isStiff = 1			
		end
	end
	
	mm.x				= obj.x
	mm.y				= obj.y
	mm.hit_id			= hitID
	mm.hit_height = hitHeight
	if heavyHit then
		mm.heavy_hit	= heavyHit
	else
		mm.heavy_hit	= 0
	end
	
	mm.stiff			= isStiff or 0
	mm.hitSound 		= utilityConfig and utilityConfig.hitSound or 0
	mm.hitEffectConfig  = hitEffectConfig or 0
  mm.blood_id = utilityConfig and utilityConfig.blood_effect or 0
  mm.bloodEffectConfig = 0
  if mm.blood_id > 0 then
    if obj.obj_type ~= Obj.TYPE_MONSTER or ObjMonster.get_conf(obj).can_blood == 1 then 
      mm.bloodEffectConfig = EffectLogic.getConfig(mm.blood_id)
    else
      mm.blood_id = 0
    end
  end
	local sender		= Obj.objs[senderID]
	if sender then
		local owner = sender.owner
		if owner then
			mm.ownerID = owner.id or 0
		else
			mm.ownerID = 0
		end
	else
		mm.ownerID = 0
	end
	if obj.obj_type == Obj.TYPE_HUMAN and HIDE_NO_SEND_MAP[obj.db.map_id] then
        local list = Msg.list
        Obj.getAreaHumans(list, obj.scene_id, obj.x, obj.y)
        for k = 1, list[0] do
            local tempObj = list[k]
            if tempObj.db.hide == 0 or tempObj==obj then
                Msg.send(mm, tempObj.fd)
            end
        end
  else
	     Obj.sendArea(mm, obj.scene_id, obj.x, obj.y)
	end
end

function GC_SKILL_HIT2(obj, utilityID, tid)
	local utilityConfig = UtilityExcel[utilityID]
	local hitID			= utilityConfig.hitID
	local mm = Msg.gc.GC_SKILL_HIT2
	mm.recv_id	= tid
	mm.hit_id	= hitID
	mm.hit_height = utilityConfig.hitHeight
	mm.hitEffectConfig = EffectLogic.getConfig(hitID)
	Obj.sendArea(mm, obj.scene_id, obj.x, obj.y)
end

function GC_SKILL_SPECIAL(obj, sceneID, utilityConfig, tx, ty, x, y)	
	local bombQuake		= utilityConfig.bombQuake
	local space			= utilityConfig.space
	local mm = Msg.gc.GC_SKILL_SPECIAL
	mm.obj_id = obj.id
	mm.quake = getQuake(obj, bombQuake, Obj.getDir(tx - x, ty - y))
	mm.space = space
	mm.ty = ty
	mm.tx = tx
	Obj.sendArea(mm, sceneID, x, y)
end

function hitQuake(obj,target,utilityConfig)
	local userData = Skill.getUserData(obj)
	if Timer.now - userData.hitQuake < 400 then return end
	userData.hitQuake = Timer.now
	if (#utilityConfig.hitQuake<1 or utilityConfig.hitQuake[1]<1 or (obj.obj_type ~= Obj.TYPE_HUMAN and (not utilityConfig.hitQuake[3] or utilityConfig.hitQuake[3]==1)) ) then return end
	local mm = Msg.gc.GC_SKILL_SPECIAL
	mm.obj_id = obj.id
	mm.quake = getQuake(obj, utilityConfig.hitQuake, Obj.getDir(target.x - obj.x, target.y - obj.y))
	mm.space = 0
	mm.ty = target.x
	mm.tx = target.y
	Obj.sendArea(mm, obj.scene_id, obj.x, obj.y)
end

function GC_SKILL_EFFECT(obj, sceneID, utilityConfig, x, y)

	local userData = Skill.getUserData(obj)
	local effectID = utilityConfig.enableID[userData.actionIndex] or 0
	if effectID == 0 then return end

	local mm		= Msg.gc.GC_SKILL_EFFECT
	mm.obj_id		= obj.id
	mm.effectID		= effectID
	mm.effectConfig = EffectLogic.getConfig(effectID)
	Obj.sendArea(mm, sceneID, x, y)
end


function GC_SKILL_LINK(human, id, nextID, expire)
 
  local mm = Msg.gc.GC_SKILL_LINK
  local firstID = id
  local skillConfig = SkillExcel[id]
  while skillConfig and skillConfig.linkparent do
       firstID = skillConfig.linkparent
       skillConfig = SkillExcel[firstID]
  end
  mm.groupID = firstID
  nextID = nextID or firstID  
  mm.skillID = nextID  
  skillConfig = SkillExcel[nextID]
        
  mm.time = SkillExcel[id].qianyao_sec * 1000
  mm.count = 0
  if nextID == firstID then
      mm.expire = 0
  else
      mm.expire = expire or 10000
  end
  
  Msg.send(mm, human.fd)
end

local dirs = dirs or {
	[0]= 4,
	[1]= 7,
	[2]= 5,
	[3]= 1,
	[4]= 3,
	[5]= 2,
	[6]= 6,
	[7]= 8,
}
-- 获取震屏方式
function getQuake(obj, config, fixdir)
	if #config<1 or config[1]==0 then return 0 end
	local dir = config[1]
	if dir==9 then
		dir = fixdir and dirs[fixdir] or dirs[obj.dir]
	end
	return dir + (config[2] or 1)*100 + (config[3] or 1)*10000 + (config[4] or 200)*100000
end


function GC_SKILL_NEW(human, index, skillID)
  local msg = Msg.gc.GC_SKILL_NEW
  msg.index = index
  msg.icon  = SkillExcel[skillID].icon
  Msg.send(msg, human.fd)
end
